package xin.yangshuai.mybatisgeneratorweb.util;


import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.MessageFormat;

/**
 * DownloadUtils
 *
 * @author shuai
 * @date 2020/11/26
 */
public class DownloadUtils {

    private static final Logger log = LoggerFactory.getLogger(DownloadUtils.class);

    private static final String IE_USER_AGENT = "msie";
    private static final String IE_BROWSER = "IE";

    private static final String EDGE_USER_AGENT = "edge";
    private static final String EDGE_BROWSER = "EDGE";

    private static final String OPERA_USER_AGENT = "opera";
    private static final String OPERA_BROWSER = "OPERA";

    private static final String SAFARI_USER_AGENT = "safari";
    private static final String SAFARI_BROWSER = "SAFARI";

    private static final String CHROME_USER_AGENT = "applewebkit";
    private static final String CHROME_BROWSER = "CHROME";

    private static final String FIREFOX_USER_AGENT = "mozilla";
    private static final String FIREFOX_BROWSER = "FIREFOX";


    private static String attachmentFilename = "attachment;fileName{0}";


    /**
     * 下载
     *
     * @param bytes
     * @param filename
     * @param request
     * @param response
     * @throws Exception
     */
    public static void download(byte[] bytes, String filename, HttpServletRequest request, HttpServletResponse response) throws Exception {

        byte[] buffer = new byte[1024];

        //强制下载
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", getAttachmentFilename(request, filename));

        BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(bytes));
        OutputStream outputStream = response.getOutputStream();
        int len;
        while ((len = bis.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
        }
    }

    public static void download(File file, HttpServletRequest request, HttpServletResponse response) throws Exception {

        String filename = file.getName();

        byte[] buffer = new byte[1024];

        //强制下载
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", getAttachmentFilename(request, filename));

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        OutputStream outputStream = response.getOutputStream();
        int len;
        while ((len = bis.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
        }
        outputStream.close();
        bis.close();
    }


    /**
     * 获取attachmentFilename
     *
     * @param request
     * @param filename
     * @return
     * @throws Exception
     */
    private static String getAttachmentFilename(HttpServletRequest request, String filename) throws Exception {

        String browser = getBrowser(request);
        String newFilename = URLEncoder.encode(filename, "UTF-8");

        String attachmentFilenameURLEncoder = MessageFormat.format(attachmentFilename, "=" + newFilename);
        String attachmentFilenameUTF8 = MessageFormat.format(attachmentFilename, "*=UTF-8''" + newFilename);
        String attachmentFilenameISO = MessageFormat.format(attachmentFilename, "=" + new String(filename.getBytes("UTF-8"), "iso-8859-1"));
        String attachmentFilenameMimeUtility = MessageFormat.format(attachmentFilename, "=" + MimeUtility.encodeText(filename, "UTF8", "B"));

        switch (browser) {
            case EDGE_BROWSER:
                // edge浏览器
                return attachmentFilenameURLEncoder;
            case IE_BROWSER:
                // IE浏览器，只能采用URLEncoder编码（只适用于IE11以下,因为在IE11中UserAgent不再包含MSIE字符串）
                return attachmentFilenameURLEncoder;
            case OPERA_BROWSER:
                // Opera浏览器只能采用filename*
                return attachmentFilenameUTF8;
            case SAFARI_BROWSER:
                // Safari浏览器，只能采用ISO编码的中文输出（苹果的）
                return attachmentFilenameISO;
            case CHROME_BROWSER:
                // Chrome浏览器，只能采用MimeUtility编码或ISO编码的中文输出
                // 实际上，这段代码不会走，因为到目前为止，谷歌浏览器的userAgent中存在safari。但因为谷歌浏览器兼容safari，所以，谷歌浏览器也好使
                return attachmentFilenameMimeUtility;
            case FIREFOX_BROWSER:
                // FireFox浏览器，可以使用MimeUtility或filename*或ISO编码的中文输出
                // IE11和FireFox会走这个
                // 1. 之所以会使用mozilla判断，而不是FireFox，是因为Mozilla一般浏览器都有，可以作为默认的；二来FireFox前身是mozilla，所以FireFox中的userAgent自带mozilla参数。
                // 2. IE11中的userAgent去掉了MSIE。可以认为IE11开始，逐渐向标准化靠拢。
                return attachmentFilenameUTF8;
            default:
                return attachmentFilenameURLEncoder;
        }
    }

    /**
     * 获取浏览器类型
     *
     * @param request
     * @return
     */
    private static String getBrowser(HttpServletRequest request) {
        String userAgent = request.getHeader("USER-AGENT");
        if (userAgent != null) {
            userAgent = userAgent.toLowerCase();
            if (userAgent.indexOf(EDGE_USER_AGENT) != -1) {
                log.info("当前浏览器是edge");
                return EDGE_BROWSER;
            }
            if (userAgent.indexOf(IE_USER_AGENT) != -1) {
                log.info("当前浏览器是ie11以下");
                return IE_BROWSER;
            }
            if (userAgent.indexOf(OPERA_USER_AGENT) != -1) {
                log.info("当前浏览器是opera");
                return OPERA_BROWSER;
            }
            if (userAgent.indexOf(SAFARI_USER_AGENT) != -1) {
                log.info("当前浏览器是safari或者chrome");
                return SAFARI_BROWSER;
            }
            if (userAgent.indexOf(CHROME_USER_AGENT) != -1) {
                log.info("当前浏览器是chrome");
                return CHROME_BROWSER;
            }
            if (userAgent.indexOf(FIREFOX_USER_AGENT) != -1) {
                log.info("当前浏览器是firefox或者ie11");
                return FIREFOX_BROWSER;
            }
        }
        return null;
    }
}